package com.atguigu.crowd.handler;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.crowd.api.MySQLRemoteService;
import com.atguigu.crowd.api.RedisRemoteService;
import com.atguigu.crowd.config.ShortMessageProperties;
import com.atguigu.crowd.entity.po.MemberPO;
import com.atguigu.crowd.entity.vo.MemberLoginVO;
import com.atguigu.crowd.entity.vo.MemberVO;
import com.atguigu.crowd.util.CrowdConstant;
import com.atguigu.crowd.util.CrowdUtil;
import com.atguigu.crowd.util.ResultEntity;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Controller
public class MemberHandler {

    @Autowired
    private ShortMessageProperties shortMessageProperties;

    @Autowired
    private RedisRemoteService redisRemoteService;

    @Autowired
    private MySQLRemoteService mySQLRemoteService;


    @RequestMapping("/auth/member/logout")
    public String logout(HttpSession session){
        session.invalidate();

        return "redirect:/";
    }

    @ResponseBody
    @RequestMapping("/auth/member/do/login")
    public ResultEntity<String> doLogin(@RequestParam("loginacct") String loginacct,
                                        @RequestParam("userpswd") String userpswd,
                                        HttpSession session){
        //调用远程接口查询用户信息
        ResultEntity<MemberPO> resultEntity = mySQLRemoteService.getMemberPOByLoginAcctRemote(loginacct);

        if (ResultEntity.ERROR.equals(resultEntity.getResult())) {

            return ResultEntity.errorData(resultEntity.getMessage());
        }

        MemberPO memberPO = resultEntity.getData();

        if (memberPO == null){
            return ResultEntity.errorData(CrowdConstant.MESSAGE_LOGIN_FAILED);
        }

        // 比较密码
        String userpswdDatabase = memberPO.getUserpswd();

        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

        boolean matches = passwordEncoder.matches(userpswd, userpswdDatabase);

        if (!matches){
            return ResultEntity.errorData(CrowdConstant.MESSAGE_LOGIN_FAILED);
        }

        //创建MemberLoginVo对象存入session
        MemberLoginVO memberLoginVO = new MemberLoginVO(memberPO.getId(), memberPO.getUsername(), memberPO.getEmail());

        session.setAttribute(CrowdConstant.ATTR_NAME_LOGIN_MEMBER,memberLoginVO);

        return ResultEntity.successResuleData("/auth/member/to/center/page");

    }

    @RequestMapping("/auth/do/member/register")
    public String register(MemberVO memberVO, ModelMap modelMap){
        // 获取登陆手机号
        String phone = memberVO.getPhone();

        // 拼接Redis中存储的验证码的key
        String key = CrowdConstant.REDIS_CODE_PREFIX + phone;

        // 读取对应的key的value
        ResultEntity<String> redisStringValueByKey = redisRemoteService.getRedisStringValueByKey(key);

        // 检查redis查询操作是否有效
        String result = redisStringValueByKey.getResult();
        if (ResultEntity.ERROR.equals(result)){
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,redisStringValueByKey.getMessage());

            return "member-reg";
        }

        String redisCode = redisStringValueByKey.getData();
        if (redisCode == null){
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,CrowdConstant.MESSAGE_CODE_NOT_EXISTS);

            return "member-reg";
        }

        // 如果能够查询到则比较表单验证码和redis验证码
        String formCode = memberVO.getCode();

        if(!Objects.equals(formCode,redisCode)){
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,CrowdConstant.MESSAGE_CODE_INVALID);

            return "member-reg";
        }
        // 如果验证码一致则从redis删除
        redisRemoteService.removeRedisKeyRemote(key);

        // 执行密码加密
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String userpswd = memberVO.getUserpswd();

        String encode = bCryptPasswordEncoder.encode(userpswd);

        memberVO.setUserpswd(encode);

        // 执行保存
        //创建空的MemberPO对象
        MemberPO memberPO = new MemberPO();

        // 复制属性
        BeanUtils.copyProperties(memberVO, memberPO);

        //调用远程方法
        ResultEntity<String> stringResultEntity = mySQLRemoteService.saveMember(memberPO);

        if (ResultEntity.ERROR.equals(stringResultEntity.getResult())) {
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,stringResultEntity.getMessage());

            return "member-reg";
        }

        //使用重定向避免刷新浏览器重新执行注册流程
        return "redirect:/auth/member/to/login/page";
    }


    @RequestMapping("/auth/member/send/short/sendMessage")
    @ResponseBody
    public ResultEntity<String> senMessage(@RequestParam("phone") String phone){

        //发送验证码
        ResultEntity<String> stringResultEntity = CrowdUtil.sendCodeByShortMessage(
                shortMessageProperties.getHost(),
                shortMessageProperties.getPath(),
                phone,
                shortMessageProperties.getAppCode(),
                shortMessageProperties.getSign(),
                shortMessageProperties.getSkin());

        if(ResultEntity.SUCCESS.equals(stringResultEntity.getResult())){
            //判断成功,把验证码存入redis
            String code = stringResultEntity.getData();

            String key = CrowdConstant.REDIS_CODE_PREFIX + phone;

            //5分钟
            ResultEntity<String> saveCodeRedis = redisRemoteService.setRedisKeyValueRemoteWithTimeout(key, code, 5, TimeUnit.MINUTES);

            if(ResultEntity.SUCCESS.equals(saveCodeRedis.getResult())){
                return ResultEntity.successData();
            }else{
                return saveCodeRedis;
            }
        }else{
            return stringResultEntity;
        }
    }
}
